local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local Util = require("common.Util")
local YjTreasureExcel = require("excel.yjTreasure")
local RoleDefine = require("role.RoleDefine")
local CombatLogic = require("combat.CombatLogic")
local YjTreasureLogic = require("yjTreasure.YjTreasureLogic")
local CombatDefine = require("combat.CombatDefine")
local PanelDefine = require("broadcast.PanelDefine")
local Log = require("common.Log")
local Config = require("Config")
local CommonDB = require("common.CommonDB")
local DBUpdate = { _id = nil }
local DBUpdateField = {} --更新域

YJ_TREASURE_DB = YJ_TREASURE_DB or {}
YJ_Rank2Uuid = YJ_Rank2Uuid or {}
YJ_Uuid2Role = YJ_Uuid2Role or {}
function changeOldToNewDB()
	if _G.is_middle == true then return end

	LuaMongo.find(DB.db_yjTreasure)
	local yjTreasureDB = {}

	if not LuaMongo.next(yjTreasureDB) then
		return
	end

	YJ_TREASURE_DB = yjTreasureDB
    -- 老数据库中有数据
    if YJ_TREASURE_DB.time then
        -- 改成新数据
        CommonDB.setYjTreasureEndTime(YJ_TREASURE_DB.time)
        -- 初始化新库
        --initDB()
        -- 插入原有数据
        for uuid, roledata in pairs(YJ_TREASURE_DB.uuid2Roles) do
            roledata.uuid = uuid
            insertUuid2Role(roledata)
            YJ_Rank2Uuid[#YJ_Rank2Uuid + 1] = uuid
        end
    end
    sortYJboard()
    local removeDate = {}
    removeDate._id = yjTreasureDB._id
    LuaMongo.remove(DB.db_yjTreasure, removeDate)
end

function initAfterStart()
    if _G.is_middle == true then return end

    LuaMongo.find(DB.db_yjTreasure_role)
    while true do
        local roleDB = {}
        if not LuaMongo.next(roleDB) then
	    	return
	    end

        YJ_Uuid2Role[roleDB.uuid] = roleDB
        YJ_Rank2Uuid[#YJ_Rank2Uuid + 1] = roleDB.uuid
    end
    sortYJboard()
end

function getDBUuid2Roles()
	return YJ_Uuid2Role
end

function getDBrank2Uuid()
	return YJ_Rank2Uuid
end

function getRoleDataByUuid(uuid)
	local uuid2Roles = getDBUuid2Roles()
	if not uuid2Roles then return end

	return uuid2Roles[uuid]
end

function getLayerDataByUuid(uuid)
	local roleData = getRoleDataByUuid(uuid)
	return roleData.layerData
end

-- 获取出战英雄
function getFightHeroObj(heroList)
	if not heroList then return end
	for pos in pairs(heroList) do
		local obj = heroList[pos]
		if obj and obj.isFight == 1 and getCombatObjHp(obj) > 0 then
			return obj, pos
		end
	end
end

-- 获取当前血
function getCombatObjHp(obj)
	if obj.hp then return obj.hp end
	return obj.attrs[RoleDefine.HP] or 0
end

-- 获取最大血量
function getCombatObjHpMax(obj)
	if obj.hpMax then return obj.hpMax end
	return obj.attrs[RoleDefine.HP] or 0
end

-- 获取allshop数据
function getAllShopData(uuid)
	local roleData = getRoleDataByUuid(uuid)
	return roleData.allShop
end

function getGridsData(uuid)
	local layerData = getLayerDataByUuid(uuid)
	if not layerData then return end
	return layerData.grids
end

function getGridDataByIndex(uuid,gridIndex)
	local gridData = getGridsData(uuid)
	if not gridData then return end
	return gridData[gridIndex]
end

function getBuffData(uuid)
	local roleData = getRoleDataByUuid(uuid)
	return roleData.buff
end

function getKillMonsterData(uuid)
	local roleData = getRoleDataByUuid(uuid)
	return roleData.killMonster
end

function getRankByUuid(uuid)
	local rank2Uuid = getDBrank2Uuid()
	for i=1,#rank2Uuid do
		if uuid == rank2Uuid[i] then return i end
	end

	return 0
end

function getObjList(uuid)
	local roleData = getRoleDataByUuid(uuid)
	return roleData.objList
end

function insertUuid2Role(roleDB)
	LuaMongo.insert(DB.db_yjTreasure_role,roleDB)
    YJ_Uuid2Role[roleDB.uuid] = roleDB
end

function updateUuid2Role(roleDB,uuid)
    DBUpdate = {}
	DBUpdate.uuid = roleDB.uuid

	LuaMongo.update(DB.db_yjTreasure_role, DBUpdate, roleDB)
    YJ_Uuid2Role[roleDB.uuid] = roleDB
end

function updateRank2Uuid(rankDB)
    YJ_Uuid2Role[rankDB.rank] = rankDB.uuid
end

--更新楼层信息
function updateLayerData(uuid,layerData)
	local roleData = getRoleDataByUuid(uuid)
	roleData.layerData = layerData

	updateUuid2Role(roleData)
end

--更新格子信息
function updateGridsData(uuid,gridsData)
	local roleData = getRoleDataByUuid(uuid)
	roleData.layerData.grids = gridsData
	updateUuid2Role(roleData)
end

--更新db中排名信息
function updateYJRank(rank2Uuid)
	YJ_Rank2Uuid = rank2Uuid
end

-- 设置出战
function setFightHero(heroList, tpos)
	if not heroList then return end
	if tpos and heroList[tpos] and getCombatObjHp(heroList[tpos]) <= 0 then
		return -- 手动设置的出战对象不存在或者血量小于0
	end

	for pos in pairs(heroList) do
		local obj = heroList[pos]
		if obj then
			obj.isFight = 0
		end
		if obj and tpos == nil and getCombatObjHp(obj) > 0 then
			tpos = pos -- 自动选择出战
		end
	end	

	if not tpos then return end
	local obj = heroList[tpos]
	obj.isFight = 1
	return true
end

--活动db中增加玩家
function addPlayer(objList,rolebase,uuid)
	local uuid2Roles = YJ_Uuid2Role or {}
	local rank2Uuid = YJ_Rank2Uuid or {}

	local roleData = {
	objList = Util.copyTable(objList), --上阵英雄
	rolebase = Util.copyTable(rolebase), --人物信息
	layerData = nil, --当层信息(层数+格子信息)
	layerMax = nil, --历史最高层
	tansuo = nil, --探索度（已翻开格子数量）
	allShop = nil, --探险商城（包含神秘商人和商店所出现的所有道具）
	yjShoperCnt = nil, --遗迹商人
	killMonster = nil, --达标奖励 killMonster.killCnt = 0 killMonster.getList[id]
	yaojis = nil, --药剂（生命+死亡）yaojis[type1].nowCnt yaojis[type1].useCnt
	buff = nil, --属性加成 buff[key] = value
	sangdang = nil, --已扫荡次数
	time = os.time(), --参加时间
    item = nil,          -- 累计道具
    uuid = uuid,         -- uuid
}
	creatLayerData(roleData,1)
	setFightHero(roleData.objList)

	uuid2Roles[uuid] = roleData
    insertUuid2Role(roleData)

	rank2Uuid[#rank2Uuid + 1] = uuid

	return uuid2Roles[uuid]
end

--根据格子类型获得当前已生成格子中已有该类型的数量
local function getCntByGridType(grids,gridType)
	if not grids then return 0 end

	local cnt = 0
	for index,data in pairs(grids) do
		if data.gridType == gridType then
			cnt = cnt + 1
		end
	end

	return cnt
end

local function getOpenGroupByIndex(gridIndex)
	local killOpenGridsCnf = YjTreasureExcel.define[1].killOpenGrids
	for i=1,#killOpenGridsCnf do
		for j=1,#killOpenGridsCnf[i] do
			if gridIndex == killOpenGridsCnf[i][j] then
				return i
			end
		end
	end
end

local function getKeyIndexByGroupID(openGroupID)
	local keyGroup = nil
	if openGroupID == 4 then
		keyGroup = 1
	elseif openGroupID == 1 then
		keyGroup = 4
	elseif openGroupID == 2 then
		keyGroup = 3
	elseif openGroupID == 3 then
		keyGroup = 2
	end

	local killOpenGridsCnf = YjTreasureExcel.define[1].killOpenGrids[keyGroup]
	local random = math.random(1,#killOpenGridsCnf)
	return killOpenGridsCnf[random]
end

--根据层数创造格子信息
function createGrids(layer,grids)
	local defCnf = YjTreasureExcel.define[1]
	local layCnf = YjTreasureExcel.layer[layer]
	local gridCnf = YjTreasureExcel.grid
	
	local keyIndex = nil

	for gridIndex=1,YjTreasureLogic.YJ_TREASURE_GRID_MAX do
		local grid = {
		gridType = nil, --格子类型
		monsterObjList = nil, --格子为怪物或boss时，记录outID中的objList
		monsterRBase = nil, --怪物基本信息
		item = nil, --格子为道具时，记录道具{id,cnt} 
		soul = nil, --灵魂拷问 soulID
		question = nil, --博闻强识
		treasureShop = nil, --商店
		isOpen = nil, --是否打开
	}

		for monsterGrid=1,#defCnf.monstersGrid do
			if gridIndex == defCnf.monstersGrid[monsterGrid] then
				grid.gridType = YjTreasureLogic.YJ_TREASURE_GRID_MONSTER
				local objList,_,rolebase = CombatLogic.getMonsterObjList(layCnf.monsters[monsterGrid])
				grid.monsterObjList = Util.copyTable(objList)
				grid.monsterRBase = Util.copyTable(rolebase)
				grid.isOpen = 1
			end
		end

		if gridIndex == defCnf.bossGrid then
			grid.gridType = YjTreasureLogic.YJ_TREASURE_GRID_BOSS
			local objList,_,rolebase = CombatLogic.getMonsterObjList(layCnf.boss)
			grid.monsterObjList = Util.copyTable(objList)
			grid.monsterRBase = Util.copyTable(rolebase)
			grid.isOpen = nil
		end

		if keyIndex and keyIndex == gridIndex then
			grid.gridType = YjTreasureLogic.YJ_TREASURE_GRID_KEY
			keyIndex = nil
		end

		if not grid.gridType then
			local totalWeight = 0
			for i=1,#gridCnf do
				local nowCnt = getCntByGridType(grids,i)
				if nowCnt < gridCnf[i].openMax or gridCnf[i].openMax == 0 then
					totalWeight = totalWeight + gridCnf[i].weight
				end
			end

			local random = math.random(1,totalWeight)
			local randWeight = 0
			for i=1,#gridCnf do
				local nowCnt = getCntByGridType(grids,i)
				if nowCnt < gridCnf[i].openMax or gridCnf[i].openMax == 0 then
					if gridCnf[i].weight ~= 0 then
						randWeight = randWeight + gridCnf[i].weight
						if random <= randWeight then
							grid.gridType = i
							if grid.gridType == YjTreasureLogic.YJ_TREASURE_GRID_BOX then --宝箱特殊处理 安置钥匙
								local openGroupID = getOpenGroupByIndex(gridIndex)
								keyIndex = getKeyIndexByGroupID(openGroupID)
								--print("keyIndex",keyIndex)
								if keyIndex < gridIndex then
									grids[keyIndex] = {}
									grids[keyIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_KEY
								end
							end

							if grid.gridType == YjTreasureLogic.YJ_TREASURE_GRID_ITEM then --权重道具生成
								local layerItemsCnf = layCnf.layerItems
								local totalItemWeight = 0
								for j=1,#layerItemsCnf do
									totalItemWeight = totalItemWeight + layerItemsCnf[j][3]
								end

								local randItem = math.random(1,totalItemWeight)
								local randItemWight = 0
								for g=1,#layerItemsCnf do
									randItemWight = randItemWight + layerItemsCnf[g][3]
									if randItem <= randItemWight then
										grid.item = {}
										grid.item.itemID = layerItemsCnf[g][1]
										grid.item.itemCnt = layerItemsCnf[g][2]
										break
									end
								end
							end

							break
						end
					end
				end
			end
		end
		grids[gridIndex] = grid
		-- if grids[gridIndex].gridType == YjTreasureLogic.YJ_TREASURE_GRID_ITEM then
		-- 	require("common.Util").printTable(grids[gridIndex])
		-- end
	end
	
	return grids
end

--创建层的信息
function creatLayerData(roleData,layer)
	local layerData = {
	layer = layer, --层数
	grids = {}, --格子信息
	getItems = nil, --本层中所获得的物品 getItems[ID] = cnt
}
	createGrids(layer,layerData.grids)

	roleData.layerData = layerData

	return layerData
end

function creatLayerDataByUuid(uuid,layer)
	local roleData = getRoleDataByUuid(uuid)
	local layerData = creatLayerData(roleData,layer)
	updateUuid2Role(roleData)

	return layerData
end

--神秘商人刷出的道具 和 商店刷出的道具 都会加入列表中
function addItems2AllShop(uuid,shopType,items)
	local roleData = getRoleDataByUuid(uuid)
	local allShopIDList = {}
	roleData.allShop = roleData.allShop or {}
	for i=1,#items do
		local shopItem = {
		shopType = shopType,
		shopConfID = items[i],
		isBuy = nil, --已购买
	}
		local index = #roleData.allShop + 1
		roleData.allShop[index] = shopItem
		allShopIDList[#allShopIDList + 1] = index
	end

	return allShopIDList
end

--创建商店三个权重物品
function makeTreasureShop(uuid,gridIndex)
	local roleData = getRoleDataByUuid(uuid)
	local layerData = roleData.layerData
	local gridData = layerData.grids[gridIndex]

	local treasureShopCnf = YjTreasureExcel.treasureShop
	local randItem = {}
    local randCnt = math.random(1,3)
	for rand=1,randCnt do
		local totalWeight = 0
		for i=1,#treasureShopCnf do
			if not randItem[i] then
				totalWeight = totalWeight + treasureShopCnf[i].weight 
			end
		end
		local randWeight = math.random(1,totalWeight)
		local weight = 0
		for i=1,#treasureShopCnf do
			if not randItem[i] then
				weight = weight + treasureShopCnf[i].weight 
				if randWeight <= weight then
					randItem[i] = i

					break
				end
			end
		end
	end

	local items = {}
	for treasureShopID in pairs(randItem) do
		items[#items + 1] = treasureShopID
	end
	local allShopIDList = addItems2AllShop(uuid,YjTreasureLogic.YJ_SHOP_TREASURE_SHOP,items)

	gridData.treasureShop = {}
	for i=1,#allShopIDList do
		gridData.treasureShop[#gridData.treasureShop + 1] = allShopIDList[i]
	end

	updateUuid2Role(roleData)
end

--设置玩家购买商品
function setShopItemBuy(uuid,allShopID)
	local roleData = getRoleDataByUuid(uuid)
	roleData.allShop[allShopID].isBuy = allShopID
	updateUuid2Role(roleData)
end

--创造灵魂拷问题
function makeSoul(uuid,gridIndex)
	local gridsData = getGridsData(uuid)
	local soulCnf = YjTreasureExcel.soul
	local totalWeight = 0
	for i=1,#soulCnf do
		totalWeight = totalWeight + soulCnf[i].weight
	end

	local rand = math.random(1,totalWeight)
	local weight = 0
	for i=1,#soulCnf do
		weight = weight + soulCnf[i].weight
		if rand <= weight then
			gridsData[gridIndex].soul = i
			updateGridsData(uuid,gridsData)
			return i
		end
	end
end

--创造博闻强识问题
function makeQuestion(uuid,gridIndex)
	local gridsData = getGridsData(uuid)
	local questionData = {
	rightCnt = nil, --答对次数
	answer = nil, --已回答 answer[id] = select
	list = {}, --问题列表
}

	local questionCnf = YjTreasureExcel.question
	local randList = {}
	for i=1,3 do
		local totalWeight = 0
		for question=1,#questionCnf do
			if not randList[question] then
				totalWeight = totalWeight + questionCnf[i].weight
			end
		end

		local rand = math.random(1,totalWeight)
		local weight = 0
		for question=1,#questionCnf do
			if not randList[question] then
				weight = weight + questionCnf[question].weight
				if rand <= weight then
					randList[question] = true
					questionData.list[i] = question
					break
				end
			end
		end
	end
	gridsData[gridIndex].question = questionData
	updateGridsData(uuid,gridsData)

	return questionData
end

--权重遗迹商人商品
function makeYjShoperItem(uuid)
	local roleData = getRoleDataByUuid(uuid)
	local yjShoperCnf = YjTreasureExcel.yjShoper
	local totalWeight = 0
	for i=1,#yjShoperCnf do
		totalWeight = totalWeight + yjShoperCnf[i].weight
	end
	local rand = math.random(1,totalWeight)
	local weight = 0
	local item = {}
	for yjShoperCnfID=1,#yjShoperCnf do
		weight = weight + yjShoperCnf[yjShoperCnfID].weight
		if rand <= weight then
			item[1] = yjShoperCnfID
            break
		end
	end
	local allShopIDList = addItems2AllShop(uuid,YjTreasureLogic.YJ_SHOP_YJSHOPER,item)
	return allShopIDList[1],item[1]
end

function makeBuff(uuid)
	local roleData = getRoleDataByUuid(uuid)
	local buffConf = YjTreasureExcel.buff
	local totalWeight = 0
	for i=1,#buffConf do
		totalWeight = totalWeight + buffConf[i].weight
	end

    local buffAttr = nil
	local rand = math.random(1,totalWeight)
	local weight = 0
	for i=1,#buffConf do
		weight = weight + buffConf[i].weight
		if rand <= weight then
			roleData.buff = roleData.buff or {}
			local key = buffConf[i].gap[1]
			local value = buffConf[i].gap[2]
			roleData.buff[key] = (roleData.buff[key] or 0) + value
            buffAttr = {key,value}
			break
		end
	end
    return buffAttr
end

--排行榜
local function cmpYJRank(auuid, buuid)
	local aRoleData = getRoleDataByUuid(auuid)
	local bRoleData = getRoleDataByUuid(buuid)

	local aLayerData = aRoleData.layerData
	local bLayerData = bRoleData.layerData
    if not aLayerData or not bLayerData then
        return
    end
	if aLayerData.layer ~= bLayerData.layer then
		return aLayerData.layer > bLayerData.layer
	end
	
	local aTansuo = aRoleData.tansuo or 0
	local bTansuo = bRoleData.tansuo or 0

	if aTansuo ~= bTansuo then
		return aTansuo > bTansuo
	end

	return aRoleData.time > bRoleData.time
end

function sortYJboard()
	local rank2Uuid = getDBrank2Uuid()
	if not rank2Uuid then return end

	table.sort(rank2Uuid, cmpYJRank)
	updateYJRank(rank2Uuid)
end

--改变格子属性
function gridTypeChange(uuid,gridsData,gridIndex,gridType,isOpen)
	gridsData[gridIndex] = {}
	gridsData[gridIndex].gridType = gridType
	
	if isOpen then
		isOpen = 1
	end
	gridsData[gridIndex].isOpen = isOpen
	updateGridsData(uuid,gridsData)

	return gridsData[gridIndex]
end

function addItem(item,uuid)
	local roleData = getRoleDataByUuid(uuid)
    roleData.item = roleData.item or {}
    for k,v in pairs(item) do
        roleData.item[k] = roleData.item[k] or 0
        roleData.item[k] = roleData.item[k] + v
    end
    updateUuid2Role(roleData)
end